/* ===================

AX2E (AXESCON XACML 2.0 Engine) is the Java authorization engine, which implements OASIS XACML 2.0 standard.
Copyright (C) 2007 AXESCON LLC

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA


Contact: AXESCON LLC - info{at}axescon.com

 =================== */
package axescon.xacml.engine;

import axescon.xacml.api.*;
import axescon.xacml.model.ctx.XacmlCtx;
import axescon.xacml.model.policy.IdReference;
import axescon.xacml.model.policy.PolicyObject;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * @author argyn
 *         Date: Oct 6, 2005
 *         Responsibilities: uses other stores to match and resolve
 */
public class PolicyStoreFederation implements PolicyReferenceStore, PolicyStore {

    /**
     * List<PolicyStore>
     */
    private List policyStoreList = new ArrayList();
    /**
     * List<PolicyReferenceStore>
     */
    private List policyReferenceStoreList = new ArrayList();


    /**
     * find a policy(s), which (target) matches a given request.
     * there can be more than one found. t's up to a caller to decide what to
     * do with more than one policy matching.
     *
     * @param req
     * @param ch
     * @return List<PolicyObject>
     */
    public List find(XacmlCtx req, CtxHandler ch, TargetMatcher tm) throws XacmlException
            , TargetMatchIndeterminateException {
        ArrayList ret = new ArrayList(1);
        Iterator it = getPolicyStoreList().iterator();
        while (it.hasNext()) {
            PolicyStore p = (PolicyStore) it.next();
            List fpl = p.find(req, ch, tm);
            if (p != null) ret.addAll(fpl);
        }
        return ret;
    }

    /**
     * loads a policy by Id
     *
     * @param idRef
     * @return
     */
    public PolicyObject resolve(IdReference idRef) throws XacmlException,
            UnresolvedIdReferenceException, DuplicateIdReferenceException {
        //this can only be a processing problem in engine code
        assert idRef != null: "Null IdReference passed to PolicyStoreFederation.";

        //this can only be a processing problem in engine code
        assert idRef.getId() != null: "PolicyStoreFederation: id is missing in id reference object.";

        PolicyObject ret = null;

        Iterator it = getPolicyReferenceStoreList().iterator();
        while (it.hasNext()) {
            PolicyReferenceStore p = (PolicyReferenceStore) it.next();
            PolicyObject po = null;
            try {
                po = p.resolve(idRef);
            } catch (XacmlException e) {// no problem, we'll try another store
                continue;
            }
            if (ret != null)
                throw new DuplicateIdReferenceException(idRef.getId(),
                        XacmlException.ERR_CODE_PROCESSING_DUPLICATE_POLICY_REFERENCE);
            ret = po;
        }
        if (ret == null)
            throw new UnresolvedIdReferenceException("PolicyStoreFederation cant find a policy/set id:" + idRef.getId(),
                    XacmlException.ERR_CODE_PROCESSING_ID_REFERENCE_NOT_FOUND);

        return ret;
    }

    public List getPolicyStoreList() {
        return policyStoreList;
    }

    public void setPolicyStoreList(List policyStoreList) {
        this.policyStoreList = policyStoreList;
    }

    public List getPolicyReferenceStoreList() {
        return policyReferenceStoreList;
    }

    public void setPolicyReferenceStoreList(List policyReferenceStoreList) {
        this.policyReferenceStoreList = policyReferenceStoreList;
    }

    public PolicyStoreFederation(PolicyStore[] ps, PolicyReferenceStore[] prs) {

        policyStoreList.addAll(Arrays.asList(ps));
        policyReferenceStoreList.addAll(Arrays.asList(prs));

    }

    public PolicyFactory getPolicyFactory() {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    public void setPolicyFactory(PolicyFactory policyFactory) {
        //To change body of implemented methods use File | Settings | File Templates.
    }
    public void validate(PolicyEvaluator pe) throws XacmlException {
        Iterator it= policyStoreList.iterator();
        String polId="unknown";
            while(it.hasNext()){
                PolicyStore ps= (PolicyStore)it.next();
                ps.validate(pe);
            }

            it= policyReferenceStoreList.iterator();
            while(it.hasNext()){
                PolicyReferenceStore prs= (PolicyReferenceStore)it.next();
                if(policyStoreList.contains(prs))continue;
                prs.validate(pe);
            }

    }
}
